package com.hanser.hancoder.core.saver;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.hanser.hancoder.constant.AppConstant;
import com.hanser.hancoder.exception.ErrorCode;
import com.hanser.hancoder.exception.ThrowUtils;
import com.hanser.hancoder.model.enums.CodeGenTypeEnum;

import java.io.File;
import java.nio.charset.StandardCharsets;

/**
 * 抽象代码文件保存模板
 */
public abstract class CodeFileSaverTemplate<T> {

    /**
     * 文件保存根目录
     */
    private static final String FILE_SAVE_ROOT_DIR = AppConstant.CODE_OUTPUT_ROOT_DIR;

    /**
     * 将内容写入指定单个文件
     *
     * @param dirPath  目录路径
     * @param filename 文件名
     * @param content  文件内容
     */
    public final void writeToFile(String dirPath, String filename, String content) {
        if (StrUtil.isNotBlank(content)) {
            String filePath = dirPath + File.separator + filename;
            FileUtil.writeString(content, filePath, StandardCharsets.UTF_8);
        }
    }

    /**
     * 构建唯一的目录路径
     *
     * @param appId 应用ID
     * @return 唯一的目录路径
     */
    protected String buildUniqueDir(Long appId) {
        ThrowUtils.throwIf(appId == null, ErrorCode.PARAMS_ERROR, "appId不能为空");
        // 获取代码生成类型
        String codeType = getCodeGenType().getValue();
        // 生成唯一目录名：类型 + 雪花算法ID
        String uniqueDirName = StrUtil.format("{}_{}", codeType, appId);
        // 拼接完整目录路径
        String dirPath = FILE_SAVE_ROOT_DIR + File.separator + uniqueDirName;
        // 创建目录
        FileUtil.mkdir(dirPath);
        return dirPath;
    }

    /**
     * 获取代码生成类型
     *
     * @return 代码生成类型枚举
     */
    protected abstract CodeGenTypeEnum getCodeGenType();

    /**
     * 保存代码文件的模板方法
     *
     * @param result 代码生成结果
     * @param appId  应用ID
     * @return 保存目录的File对象
     */
    public final File saveCode(T result, Long appId) {
        // 1.验证输入
        validateInput(result);
        // 2.构建唯一目录
        String baseDirPath = buildUniqueDir(appId);
        // 3.保存文件(具体实现由子类实现)
        saveFile(result, baseDirPath);
        // 4.返回保存的目录File对象
        return new File(baseDirPath);
    }

    /**
     * 验证输入参数
     * 可以由子类复写
     *
     * @param result 代码生成结果
     */
    protected void validateInput(T result) {
        ThrowUtils.throwIf(result == null, ErrorCode.PARAMS_ERROR, "代码结果对象不能为空");
    }

    /**
     * 保存文件抽象方法，由子类实现具体逻辑
     *
     * @param result      代码生成结果
     * @param baseDirPath 基础目录路径
     */
    protected abstract void saveFile(T result, String baseDirPath);
}
